package com.hup.sidebar.view;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.hup.sidebar.R;
import com.hup.sidebar.SideBarApplication;
import com.hup.sidebar.framework.SubThreadHandler;
import com.hup.sidebar.framework.util.AsyncDrawableTask;
import com.hup.sidebar.framework.util.SystemUtil;
import com.hup.sidebar.framework.util.ToastUtil;
import com.hup.sidebar.framework.view.BaseAdapter;
import com.hup.sidebar.framework.view.BaseViewHolder;
import com.hup.sidebar.model.AppInfoItem;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import butterknife.BindView;
import butterknife.ButterKnife;
import lombok.Getter;

/**
 * app选择界面
 *
 * @author hugan
 * @date 2022/6/2
 */
@SuppressLint("NonConstantResourceId")
public class SelectAppActivity extends AppCompatActivity {
    private static final String TAG = SelectAppActivity.class.getSimpleName();
    public static final int REQUEST_CODE = 22678;

    @BindView(R.id.txtNoneData)
    TextView txtNoneData;
    @BindView(R.id.btnSearch)
    ImageButton btnSearch;
    @BindView(R.id.txtSearchName)
    EditText txtSearchName;
    @BindView(R.id.lvApp)
    ListView lvApp;

    private AppItemAdapter appAdapter;

    private final ArrayList<AppInfoItem> lstApp = new ArrayList<>();

    /**
     * startActivityForResult时的传参,不使用Bundle传递
     */
    private static String requestPackage;
    /**
     * startActivityForResult返回时的结果,不使用Bundle传递
     */
    @Getter
    private static String resultPackage;

    /**
     * @param packageName 已选择的app,nullable
     */
    public static void startActivityForResult(Activity context, String packageName) {
        Log.i(TAG, "startActivityForResult: " + packageName);
        requestPackage = packageName;
        Intent intent = new Intent(context, SelectAppActivity.class);
        context.startActivityForResult(intent, REQUEST_CODE);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initView();
        initListener();
        txtSearchName.requestFocus();
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

        SideBarApplication.getBean(SubThreadHandler.class).post(() -> {
            Log.i(TAG, "获取应用列表.st");
            try {
                lstApp.clear();

                PackageManager packageManager = this.getPackageManager();
                List<PackageInfo> list = packageManager.getInstalledPackages(0);
                Log.i(TAG, "获取应用列表.ed, =" + list.size());
                for (PackageInfo info : list) lstApp.add(new AppInfoItem(info, packageManager));

                //按程序名,中文排序
                Collator collator = Collator.getInstance();
                Collections.sort(lstApp, (o1, o2) -> collator.compare(o1.name, o2.name));
            } catch (Exception e) {
                Log.e(TAG, "获取应用列表.err", e);
            }

            //lstApp.clear();//test
            this.runOnUiThread(() -> onUpdateList(lstApp));
        });
    }

    private void initView() {
        setContentView(R.layout.select_app_activity);
        ButterKnife.bind(this);

        appAdapter = new AppItemAdapter(this.getPackageManager());
        lvApp.setVisibility(View.GONE);
        lvApp.setAdapter(appAdapter);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initListener() {
        lvApp.setOnTouchListener((v, event) -> {
            //Log.i(TAG, "initListener: " + event);
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                SystemUtil.hideKeyboard(v);
                return false;
            }
            return false;
        });

        Runnable searchAction = () -> {
            String text = txtSearchName.getText().toString();
            Log.i(TAG, "txtSearchName=" + text);
            ArrayList<AppInfoItem> filtered = new ArrayList<>();
            if (text.isEmpty()) {
                filtered.addAll(lstApp);
            } else {
                for (AppInfoItem appInfo : lstApp) {
                    if (appInfo.name.contains(text) || appInfo.packageName.contains(text)) {
                        filtered.add(appInfo);
                    }
                }
            }
            onUpdateList(filtered);
        };
        txtSearchName.setOnEditorActionListener((v, actionId, event) -> {
            searchAction.run();
            return true;
        });
        btnSearch.setOnClickListener(v -> searchAction.run());

        lvApp.setOnItemClickListener((parent, view, position, id) -> {
            AppInfoItem info = appAdapter.getItem(position);
            Log.i(TAG, "info" + info);
            Intent intent = getPackageManager().getLaunchIntentForPackage(info.packageName);
            if (intent == null) {
                //此处限制了,不能选择无启动入口的app
                ToastUtil.short_(String.format(getString(R.string.cannot_launch), info.name));
            } else {
                resultPackage = info.packageName;
                setResult(RESULT_OK);
                finish();
            }
        });
    }

    /**
     * 显示数据
     */
    private void onUpdateList(List<AppInfoItem> lstApp) {
        Log.i(TAG, "onUpdateList: ");
        if (lstApp.isEmpty()) {
            txtNoneData.setText(R.string.select_app_none_data);
            txtNoneData.setVisibility(View.VISIBLE);
            lvApp.setVisibility(View.GONE);
        } else {
            appAdapter.setData(lstApp);
            txtNoneData.setVisibility(View.GONE);
            lvApp.setVisibility(View.VISIBLE);
            if (requestPackage != null) {
                //滚动到目标app
                for (int i = lstApp.size() - 1; i >= 0; i--) {
                    if (lstApp.get(i).packageName.equals(requestPackage)) {
                        lvApp.setSelection(i);
                        break;
                    }
                }
            }
        }
    }

    /**
     * 直接返回
     */
    @Override
    public void finish() {
        super.finish();
        requestPackage = null;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.gc();
    }

    public static void afterHandleActivityResult() {
        resultPackage = null;
    }

    private static class AppItemAdapter extends BaseAdapter<AppInfoItem, AppViewHolder> {
        private final PackageManager packageManager;

        public AppItemAdapter(PackageManager packageManager) {
            this.packageManager = packageManager;
        }

        @Override
        public int getLayoutResId() {
            return R.layout.select_app_item;
        }

        @Override
        public AppViewHolder createHolder() {
            return new AppViewHolder(packageManager);
        }
    }

    public static class AppViewHolder implements BaseViewHolder<AppInfoItem> {
        @BindView(R.id.imgIcon)
        ImageView imgIcon;
        @BindView(R.id.txtAppName)
        TextView txtAppName;
        @BindView(R.id.txtAppPackage)
        TextView txtAppPackage;
        @BindView(R.id.imgCheck)
        ImageView imgCheck;

        private final PackageManager packageManager;

        public AppViewHolder(PackageManager packageManager) {
            this.packageManager = packageManager;
        }

        @Override
        public void onBindView(View view) {

        }

        @SuppressLint({"StaticFieldLeak"})
        @Override
        public void bindData(int position, AppInfoItem item) {
            txtAppName.setText(item.name);
            txtAppPackage.setText(item.packageName);
            imgCheck.setVisibility(Objects.equals(requestPackage, item.packageName) ? View.VISIBLE : View.GONE);

            /*
            这里的AsyncTask不会导致内存泄露!
            说明详见 AsyncDrawableTask.onPostExecute
             */
            new AsyncDrawableTask(imgIcon) {
                @Override
                protected Drawable doInBackground(Void... voids) {
                    return item.applicationInfo.loadIcon(packageManager);
                }
            }.execute();
        }
    }

}
